//  这句话用来编程时自动提示，运行时需要注释掉！
//import * as BABYLON from '@babylonjs/core';

var canvas = document.getElementById("renderCanvas");

var startRenderLoop = function (engine, canvas) {
  engine.runRenderLoop(function () {
    if (sceneToRender && sceneToRender.activeCamera) {
      sceneToRender.render();
    }
  });
};

var engine = null;
var scene = null;
var sceneToRender = null;
var createDefaultEngine = function () {
  return new BABYLON.Engine(canvas, true, {
    preserveDrawingBuffer: true,
    stencil: true,
    disableWebGL2Support: false,
  });
};

//  通过高度图创建地形
//  创建场景（相关代码都在此处）
var createScene = function () {
  // This creates a basic Babylon Scene object (non-mesh)
  var scene = new BABYLON.Scene(engine);

  //  创建相机
  var camera = new BABYLON.ArcRotateCamera("camera", 0, 1.2, 5, BABYLON.Vector3.Zero());
  camera.attachControl(canvas, true);

  camera.upperBetaLimit = Math.PI / 2.2;

  //  创建灯光
  var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));
  light.intensity = 0.01;

  //  显示坐标轴
  showAxis(10, scene);

  //  导入村庄
  BABYLON.SceneLoader.ImportMeshAsync("", "https://assets.babylonjs.com/meshes/", "valleyvillage.glb").then((result) => {
    scene.getMeshByName("ground").material.maxSimultaneousLights = 5;
  });

  //  创建skybox
  const skybox = BABYLON.MeshBuilder.CreateBox("skybox", { size: 150 }, scene);
  const skyboxMaterial = new BABYLON.StandardMaterial("skyboxMaterial", scene);
  skyboxMaterial.backFaceCulling = false; //  关闭背面剔除
  //  立方盒子纹理(使用cubeTexture)（使用在线地址）
  //skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("Skybox/SkyCube2k/skyCube2k", scene);
  skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("https://playground.babylonjs.com/textures/skybox", scene);
  skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
  skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
  skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
  skybox.material = skyboxMaterial;

  //  创建路灯
  BABYLON.SceneLoader.ImportMeshAsync("", "https://assets.babylonjs.com/meshes/", "lamp.babylon", scene).then(() => {
    //  设置灯光
    const lampLight = new BABYLON.SpotLight("lampLight", new BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, -1, 0), 0.8*Math.PI, 0.01, scene);
    lampLight.diffuse = new BABYLON.Color3.Yellow();
    lampLight.parent = scene.getMeshByName("bulb");

    // 获取路灯
    const lamp = scene.getMeshByName("lamp");
    lamp.position = new BABYLON.Vector3(2, 0, 2);
    lamp.rotation.y = -Math.PI / 4;

    //  克隆路灯
    const lamp2 = lamp.clone("lamp2");
    lamp2.position = new BABYLON.Vector3(2, 0, -8);

    //  克隆路灯
    const lamp3 = lamp.clone("lamp3");
    lamp3.position = new BABYLON.Vector3(-2, 0, 1);

    //  克隆路灯
    const lamp4 = lamp.clone("lamp4");
    lamp4.position = new BABYLON.Vector3(-6, 0, 0);
  });

  const adt = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
  const panel = new BABYLON.GUI.StackPanel();
  panel.width = "200px";
  panel.top = "-50px";
  panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
  panel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_BOTTOM;
  adt.addControl(panel);

  const header = new BABYLON.GUI.TextBlock();
  header.text = "白天黑夜转换";
  header.color = "white";
  header.height = "30px";  
  panel.addControl(header);

  const slider = new BABYLON.GUI.Slider();
  slider.minimum = 0;
  slider.maximum = 1;
  slider.value = 1;
  slider.width = "200px";
  slider.height = "20px";
  slider.color = "white";
  slider.background = "black";
  panel.addControl(slider);

  slider.onValueChangedObservable.add((value) => {
    if(light){
      light.intensity = value;
    }
  });

  return scene;
};




//  创建文字平面
const makeTextPlane = (text, color, size) => {
  const dynamicTexture = new BABYLON.DynamicTexture("dynamicTexture", 50, scene, true);
  dynamicTexture.hasAlpha = true;
  dynamicTexture.drawText(text, 5, 40, "bold 36px Arial", color, "transparent", true);

  const plane = BABYLON.MeshBuilder.CreatePlane("plane", { size: size, updatable: true }, scene);
  plane.material = new BABYLON.StandardMaterial("planeMat", scene);
  plane.material.backFaceCulling = false;
  plane.material.specularColor = new BABYLON.Color3(0, 0, 0);
  plane.material.diffuseTexture = dynamicTexture;
  return plane;
}

const showAxis = (length, scene) => {

  //  创建坐标轴x
  const xAxis = BABYLON.MeshBuilder.CreateLines("xAxis",
    {
      points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(length, 0, 0),
      new BABYLON.Vector3(length * 0.95, 0.1, 0), new BABYLON.Vector3(length, 0, 0),
      new BABYLON.Vector3(length * 0.95, -0.1, 0)]
    }, scene);
  xAxis.color = new BABYLON.Color3(1, 0, 0);
  const xText = makeTextPlane("X", "red", length / 10.0);
  xText.position = new BABYLON.Vector3(length * 0.95, -0.05 * length, 0);

  //  创建坐标轴y
  const yAxis = BABYLON.MeshBuilder.CreateLines("yAxis",
    {
      points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, length, 0),
      new BABYLON.Vector3(-0.1, length * 0.95, 0), new BABYLON.Vector3(0, length, 0),
      new BABYLON.Vector3(0.1, length * 0.95, 0)]
    }, scene);
  yAxis.color = new BABYLON.Color3(0, 1, 0);
  const yText = makeTextPlane("Y", "green", length / 10.0);
  yText.position = new BABYLON.Vector3(0.05 * length, length * 0.95, 0);

  //  创建坐标轴z
  const zAxis = BABYLON.MeshBuilder.CreateLines("zAxis",
    {
      points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, 0, length),
      new BABYLON.Vector3(0, -0.1, length * 0.95), new BABYLON.Vector3(0, 0, length),
      new BABYLON.Vector3(0, 0.1, length * 0.95)]
    }, scene);
  zAxis.color = new BABYLON.Color3(0, 0, 1);
  const zText = makeTextPlane("Z", "blue", length / 10.0);
  zText.position = new BABYLON.Vector3(0.05 * length, 0.05 * length, length * 0.95);
}


//================================================

window.initFunction = async function () {
  var asyncEngineCreation = async function () {
    try {
      return createDefaultEngine();
    } catch (e) {
      console.log(
        "the available createEngine function failed. Creating the default engine instead"
      );
      return createDefaultEngine();
    }
  };

  window.engine = await asyncEngineCreation();
  if (!engine) throw "engine should not be null.";
  startRenderLoop(engine, canvas);
  window.scene = createScene();
};
initFunction().then(() => {
  sceneToRender = scene;
});

// Resize
window.addEventListener("resize", function () {
  engine.resize();
});